#ifndef __DISPLAY_DEV_H__
#define __DISPLAY_DEV_H__


#include <drm.h>
#include <drm_fourcc.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <stdint.h>
#include <string>
#include <vector>
// #include "screens.h"
using namespace std;


class display_dev
{
    public :
        display_dev(string path);
        virtual ~display_dev();
        int mpp_display_init_element();
    protected:
        class sp_bo 
        {
            public:
            int fd;

            uint32_t width;
            uint32_t height;
            uint32_t depth;
            uint32_t bpp;
            uint32_t format;
            uint32_t flags;

            uint32_t fb_id;
            uint32_t handle;
            void *map_addr;
            uint32_t pitch;
            uint32_t size;
            sp_bo()
            {
                this->width=0;
                this->height=0;
                this->depth=0;
                this->bpp=0;
                this->format=0;
                this->flags=0;
                this->fb_id=0;
                this->handle=0;

                this->map_addr=NULL;
                this->pitch=0;
                this->size=0;
            }
            sp_bo & operator =(const sp_bo & str) 
            {
                if (this != &str){
                    this->width=str.width;
                    this->height=str.height;
                    this->depth=str.depth;
                    this->bpp=str.bpp;
                    this->format=str.format;
                    this->flags=str.flags;
                    this->fb_id=str.fb_id;
                    this->handle=str.handle;

                    this->map_addr=str.map_addr;
                    this->pitch=str.pitch;
                    this->size=str.size;
                }
                return *this;
            }
        };

        class  sp_crtc
        {
            public:
                drmModeCrtcPtr crtc;
                int pipe;
                int num_planes;
                sp_bo *xrgb_scanout;         
                sp_bo *yuvnv12_scanout;
                sp_bo *yuvnv12_scanout2;
                // sp_bo *tmp_scanout;
                sp_crtc()
                {
                    this->crtc=NULL;
                    this->pipe=0;
                    this->num_planes=0;
                    this->xrgb_scanout=NULL;
                    this->yuvnv12_scanout=NULL;
                    this->yuvnv12_scanout2 = NULL;
                }
                sp_crtc & operator =(const sp_crtc & str) 
                {
                    if (this != &str){
                        this->crtc=str.crtc;
                        this->pipe=str.pipe;
                        this->num_planes=str.num_planes;
                        this->xrgb_scanout=str.xrgb_scanout;
                        this->yuvnv12_scanout=str.yuvnv12_scanout;
                        this->yuvnv12_scanout2=str.yuvnv12_scanout2;
                    }
                    return *this;
                }
        };

        class sp_plane 
        {
            public:
            int fd;
            drmModePlanePtr plane;
            struct sp_bo *bo;
            int in_use;
            uint32_t format;

            /* Property ID's */
            uint32_t crtc_pid;
            uint32_t fb_pid;
            uint32_t zpos_pid;
            uint32_t crtc_x_pid;
            uint32_t crtc_y_pid;
            uint32_t crtc_w_pid;
            uint32_t crtc_h_pid;
            uint32_t src_x_pid;
            uint32_t src_y_pid;
            uint32_t src_w_pid;
            uint32_t src_h_pid;
            sp_plane()
            {
                this->plane=NULL;
                this->bo=NULL;
                this->in_use=0;
                this->format=0;


                this->crtc_pid=0;
                this->fb_pid=0;
                this->zpos_pid=0;
                this->crtc_x_pid=0;
                
                this->crtc_y_pid=0;
                this->crtc_w_pid=0;
                this->crtc_h_pid=0;
                this->src_x_pid=0;
                this->src_y_pid=0;
                this->src_w_pid=0;
            }
            sp_plane & operator =(const sp_plane & str) 
                {
                    if (this != &str){
                        this->plane=str.plane;
                        this->bo=str.bo;
                        this->in_use=str.in_use;
                        this->format=str.format;


                        this->crtc_pid=str.crtc_pid;
                        this->fb_pid=str.fb_pid;
                        this->zpos_pid=str.zpos_pid;
                        this->crtc_x_pid=str.crtc_x_pid;
                        
                        this->crtc_y_pid=str.crtc_y_pid;
                        this->crtc_w_pid=str.crtc_w_pid;
                        this->crtc_h_pid=str.crtc_h_pid;
                        this->src_x_pid=str.src_x_pid;
                        this->src_y_pid=str.src_y_pid;
                        this->src_w_pid=str.src_w_pid;
                    }
                    return *this;
                }
        };

        vector<drmModeConnectorPtr> mpp_dev_get_connectors();
        vector<drmModeEncoderPtr> mpp_dev_get_encoders();
        vector<sp_crtc> mpp_dev_get_crtcs();
        vector <sp_plane>mpp_dev_get_plane();
    protected:
        
         vector<drmModeConnectorPtr>  mpp_element_create_connect(int fd,uint32_t count_connectors,uint32_t *connectors) ;
        
         void mpp_element_distroy_connect(int fd,vector<drmModeConnectorPtr> connectors);

         vector<drmModeEncoderPtr>  mpp_element_create_encoder(int fd,uint32_t count_encoders,uint32_t *encoders);
         void mpp_element_distroy_encoder(int fd,vector<drmModeEncoderPtr> encoders);

         vector<sp_crtc> mpp_element_create_crtc(int fd,uint32_t count_crtcs,uint32_t *crtcs);
         void mpp_element_distroy_crtc(int fd,vector<sp_crtc> crtcs);


         vector<sp_plane> mpp_element_create_plane(int fd);
         void mpp_element_distroy_plane(int fd,vector<sp_plane> plane);
        void put_sp_plane(sp_plane *plane) ;

        int mpp_display_dev_get_fd();


        int get_supported_format(sp_plane* plane, uint32_t* format);
    private:
        void distroy_all();


        vector<drmModeConnectorPtr> connectors;
        vector<drmModeEncoderPtr> encoders;
        vector<sp_crtc> crtcs;
        vector<sp_plane> plane;
        friend class screens;
        // drmModeConnectorPtr* connectors;
        // drmModeEncoderPtr*     encoders;
        // drmModeCrtcPtr*            crtcs;


        // uint32_t count_connectors;
        // uint32_t count_encoders;
        // uint32_t count_crtcs;
        int fd;
};


#endif